/*
 * Copyright (C) 2014 TinhVan Outsourcing.
 * 
 * SoapUtils.java
 * 
 * Created on: 09-05-2014 - 16:34:49 Author: VanNT
 */
package com.media.themovieworld.util;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.SoapFault;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;

import android.net.http.AndroidHttpClient;
import android.util.Log;

import com.media.themovieworld.util.network.util.HttpUtil;

public final class SoapUtils {

    private static final String LOG_TAG = SoapUtils.class.getSimpleName();

    public static String name(String templateHtml, HashMap<String, String> values) {
        // parse the template and replace all keywords
        final StringBuffer sb = new StringBuffer();
        try {
            // find all keywords
            final Pattern patern = Pattern.compile("\\{%(.*?)%\\}");
            final Matcher matcher = patern.matcher(templateHtml);

            while (matcher.find()) {
                String keyName = matcher.group(1);
                String keyValue = values.get(keyName);
                if (keyValue == null) {
                    keyValue = "";
                }
                // replace the key with value
                matcher.appendReplacement(sb, keyValue);
            }
            matcher.appendTail(sb);

            // return the final string
            return sb.toString();
        } catch (Throwable e) {
            Log.e(LOG_TAG, "Error parsing template", e);
            return null;
        }
    }

    /**
     * Sends SOAP request to the web service.
     * 
     * @param requestContent the SOAP request XML
     * @return KvmSerializable object generated from the SOAP response XML
     * @throws Throwable
     * 
     *         Sends SOAP request to the web service.
     * 
     * @param requestContent the content of the request
     * @return {@link InputStream} containing the response content
     * @throws Throwable
     */
    public static Object sendRequest(String serviceUrl, String requestContent, String requestAction,
            String soapPropety) throws Throwable {

        // initialize HTTP post
        HttpPost httpPost = null;
        try {
            httpPost = new HttpPost(serviceUrl);
            // httpPost.addHeader("Accept-Encoding", "gzip,deflate");
            // httpPost.addHeader("Content-Length", "length");
            httpPost.addHeader("Content-Type", "text/xml;charset=UTF-8");
            if (requestAction!=null) {
            	httpPost.addHeader("SOAPAction", requestAction);
			}
        } catch (Throwable e) {
            Log.e(LOG_TAG, "Error initializing HTTP post for SOAP request", e);
            throw e;
        }

        // load content to be sent
        try {
            HttpEntity postEntity = new StringEntity(requestContent);
            httpPost.setEntity(postEntity);
        } catch (UnsupportedEncodingException e) {
            Log.e(LOG_TAG, "Unsupported ensoding of content for SOAP request", e);
            throw e;
        }
        AndroidHttpClient httpClient = HttpUtil.getAndroidHttpClient(httpPost);
        httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8");
        // send request
        HttpResponse httpResponse = null;
        try {

            httpResponse = httpClient.execute(httpPost);
        } catch (Throwable e) {
            Log.e(LOG_TAG, "Error sending SOAP request", e);
            httpClient.close();
            throw e;
        }
        Object bodyIn = null;

        // get SOAP response
        try {
            // get response code
            int responseStatusCode = httpResponse.getStatusLine().getStatusCode();

            // if the response code is not 200 - OK, or 500 - Internal error,
            // then communication error occurred
            if (responseStatusCode != 200 && responseStatusCode != 500) {
                String errorMsg =
                        "Got SOAP response code " + responseStatusCode + " "
                                + httpResponse.getStatusLine().getReasonPhrase();
            }

            // get the response content
            HttpEntity httpEntity = httpResponse.getEntity();
//            String respondEntity = EntityUtils.toString(httpEntity);
//            Log.d("ENTITY", ""+respondEntity);
            InputStream is = httpEntity.getContent();
            // create the response SOAP envelope
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER10);

            envelope.dotNet = true;
            // process SOAP response
            parseResponse(is, envelope);

            // get object
            Object obj = envelope.bodyIn;
            if (obj instanceof SoapFault) {
                throw (SoapFault) obj;
            }

            SoapObject obj2 = (SoapObject) obj;
            bodyIn = obj2.getProperty(soapPropety);

        } catch (Throwable e) {
            Log.e(LOG_TAG, "Error getting SOAP response", e);
            throw e;
        } finally {
            httpClient.close();
        }
        return bodyIn;
    }

    /**
     * Parses the input stream from the response into SoapEnvelope object.
     * 
     * @throws Throwable
     */
    private static void parseResponse(InputStream is, SoapEnvelope envelope) throws Throwable {
        try {
            XmlPullParser xp = new KXmlParser();
            xp.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
            xp.setInput(is, "UTF-8");
            envelope.parse(xp);
        } catch (Throwable e) {
            Log.e(LOG_TAG, "Error reading/parsing SOAP response", e);
            throw e;
        }
    }
    
    
}
